package top.mcwebsite.playandroid.lib.markdown.render

import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.layout.layout
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.intellij.markdown.ast.ASTNode
import org.intellij.markdown.ast.findChildOfType
import org.intellij.markdown.flavours.gfm.GFMElementTypes
import org.intellij.markdown.flavours.gfm.GFMTokenTypes

@Composable
fun MarkdownTable(
    markdownState: MarkdownState, astNode: ASTNode
) {
    val list = mutableListOf<List<@Composable () -> Unit>>()
    astNode.findChildOfType(GFMElementTypes.HEADER)?.let {
        list.add(getTableHeaders(markdownState = markdownState, astNode = it))
    }
    astNode.children.filter { it.type == GFMElementTypes.ROW }.forEach {
        list.add(getTableRow(markdownState = markdownState, astNode = it))
    }
    Table(modifier = Modifier.border(width = 1.dp, color = Color.Black, shape = RectangleShape), beforeRow = {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(1.dp)
                .background(color = Color.Black)
        )
    }, afterRow = {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(1.dp)
                .background(color = Color.Black)
        )
    }, columnCount = list.first().size, rowCount = list.size
    ) { col, row ->
        list[row][col]()
    }
}

fun getTableHeaders(
    markdownState: MarkdownState, astNode: ASTNode
): List<@Composable () -> Unit> {
    // TODO 判断对齐方式
    val list = mutableListOf<@Composable () -> Unit>()
    astNode.children.filter { it.type == GFMTokenTypes.CELL }.forEach {
        list.add {
            Row(modifier = Modifier.height(IntrinsicSize.Max)) {
                Box(
                    modifier = Modifier
                        .width(1.dp)
                        .fillMaxHeight()
                        .background(color = Color.Black)
                )
                RichText(
                    markdownState = markdownState,
                    astNode = it,
                    style = TextStyle().copy(fontWeight = FontWeight.Bold),
                    modifier = Modifier.padding(5.dp)
                )
            }
        }
    }
    return list
}

fun getTableRow(
    markdownState: MarkdownState, astNode: ASTNode
): List<@Composable () -> Unit> {
    val list = mutableListOf<@Composable () -> Unit>()
    astNode.children.filter { it.type == GFMTokenTypes.CELL }.forEach {
        list.add {
            Row(modifier = Modifier.height(IntrinsicSize.Max)) {
                Box(
                    modifier = Modifier
                        .width(1.dp)
                        .fillMaxHeight()
                        .background(color = Color.Black)
                )
                RichText(markdownState = markdownState, astNode = it, modifier = Modifier.padding(5.dp))
            }
        }
    }
    return list
}

private fun tableColumnCount(astNode: ASTNode) =
    astNode.findChildOfType(GFMElementTypes.HEADER)?.children?.count { it.type == GFMTokenTypes.CELL } ?: 0


private fun tableRowCount(astNode: ASTNode) =
    astNode.children.count { node -> node.type == GFMElementTypes.HEADER || node.type == GFMElementTypes.ROW }

@Preview
@Composable
fun PreviewTable() {
    MaterialTheme {
        Table(columnCount = 3, rowCount = 3) { col, row ->
            Box {
                Text(text = "HHHH")
            }
        }
    }
}

@Composable
fun Table(
    modifier: Modifier = Modifier,
    rowModifier: Modifier = Modifier,
    verticalLazyListState: LazyListState = rememberLazyListState(),
    horizontalScrollState: ScrollState = rememberScrollState(),
    columnCount: Int,
    rowCount: Int,
    beforeRow: (@Composable (rowIndex: Int) -> Unit)? = null,
    afterRow: (@Composable (rowIndex: Int) -> Unit)? = null,
    cellContent: @Composable (columnIndex: Int, rowIndex: Int) -> Unit
) {
    val columnWidths = remember { mutableStateMapOf<Int, Int>() }

    Box(modifier = modifier.then(Modifier.horizontalScroll(horizontalScrollState))) {
        Column {
            for (rowIndex in 0 until rowCount) {
                Column(modifier = Modifier.width(IntrinsicSize.Max)) {
                    beforeRow?.invoke(rowIndex)

                    Row(modifier = rowModifier) {
                        (0 until columnCount).forEach { columnIndex ->
                            Box(modifier = Modifier.layout { measurable, constraints ->
                                val placeable = measurable.measure(constraints)

                                val existingWidth = columnWidths[columnIndex] ?: 0
                                val maxWidth = maxOf(existingWidth, placeable.width)

                                if (maxWidth > existingWidth) {
                                    columnWidths[columnIndex] = maxWidth
                                }

                                layout(width = maxWidth, height = placeable.height) {
                                    placeable.placeRelative(0, 0)
                                }
                            }) {
                                cellContent(columnIndex, rowIndex)
                            }
                        }
                    }

                    afterRow?.invoke(rowIndex)
                }
            }
        }
    }
}
